import pygame
import sys
import os
import tkinter
import math
from tkinter import filedialog
from tkinter import messagebox
from pygame.locals import *

temproot = tkinter.Tk()
temproot.iconphoto(True, tkinter.PhotoImage(file="res/fficon.png"))
temproot.withdraw()

filetypes = [
    ("Feishu Map Files", "*.fsm"),
    ("All files", "*.*"),
]

pygame.init()
screen = pygame.display.set_mode((800, 900))
pygame.display.set_caption("Map Creator v0.1")

icon = pygame.image.load("res/fficon.png")
pygame.display.set_icon(icon)
font_f3 = pygame.font.Font("res/minecraft.ttf", 30)

chunk_x = 0
chunk_y = 0
choosed = []
used_blocks = {}
mouse_at = (0, 0)
for i in os.listdir("res/blocks"):
    used_blocks[i[0]] = pygame.image.load("res/blocks/" + i)

class Chunk:
    def __init__(self):
        self.map = []
        for i in range(50):
            tl = []
            for j in range(50):
                tl.append(' ')
            self.map.append(tl)
    def set_blocks(self, lis, key):
        for i, j in lis:
            self.map[j][i] = chr(key).upper()
    def render(self, surf):
        for i in range(50):
            for j in range(50):
                if self.map[i][j] != ' ':
                    surf.blit(used_blocks[self.map[i][j]], (j*16, i*16))
    def derive(self):
        ans = []
        for i in range(50):
            ans.append(''.join(self.map[i]))
        return ans

chunks = [[Chunk()]]
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == MOUSEMOTION:
            ex, ey = event.pos
            if ex < 800 and ey < 800:
                mouse_at = (ex // 16, ey // 16)
        if event.type == MOUSEBUTTONDOWN:
            mods = pygame.key.get_mods()
            if (mods & KMOD_ALT) and len(choosed) == 1:
                ub_co = choosed[0]
                x_min = min(ub_co[0], mouse_at[0])
                x_max = max(ub_co[0], mouse_at[0])
                y_min = min(ub_co[1], mouse_at[1])
                y_max = max(ub_co[1], mouse_at[1])
                choosed = []
                for i in range(x_min, x_max+1):
                    for j in range(y_min, y_max+1):
                        choosed.append((i, j))
            elif mods & KMOD_CTRL:
                choosed.append(mouse_at)
            else:
                choosed = [mouse_at]
        if event.type == KEYDOWN:
            mods = pygame.key.get_mods()
            if event.key in map(lambda k:ord(k.lower()), used_blocks.keys()) and not (mods & KMOD_CTRL):
                chunks[chunk_y][chunk_x].set_blocks(choosed, event.key)
                chunks[chunk_y][chunk_x].derive()
            elif event.key == K_SPACE and not (mods & KMOD_CTRL):
                chunks[chunk_y][chunk_x].set_blocks(choosed, event.key)
            elif event.key == K_LEFT and chunk_x != 0:
                chunk_x -= 1
                choosed = []
            elif event.key == K_UP and chunk_y != 0:
                chunk_y -= 1
                choosed = []
            elif event.key == K_RIGHT:
                if len(chunks[chunk_y]) == chunk_x + 1:
                    chunks[chunk_y].append(Chunk())
                chunk_x += 1
                choosed = []
            elif event.key == K_DOWN:
                if len(chunks) == chunk_y + 1:
                    chunks.append([Chunk()])
                chunk_y += 1
                choosed = []
            elif event.key == K_s and (mods & KMOD_CTRL):
                ans = []
                for i in chunks:
                    ans += list(zip(*map(lambda k:k.derive(), i)))
                for i, j in enumerate(ans):
                    ans[i] = ''.join(j)
                filename = filedialog.asksaveasfilename(filetypes = filetypes)
                if not filename:
                    messagebox.showinfo("提示", "请输入正确的文件名！")
                    continue
                if not filename.lower().endswith('.fsm'):
                    filename += '.fsm'
                with open(filename, 'w') as f:
                    print(*ans, sep='\n', end='', file=f)
            elif event.key == K_o and (mods & KMOD_CTRL):
                filename = filedialog.askopenfilename(filetypes = filetypes)
                if not filename:
                    messagebox.showinfo("提示", "请输入正确的文件名！")
                    continue
                with open(filename) as f:
                    tmp = list(map(lambda k:k.rstrip('\n'), f.readlines()))
                    maxl = max(map(len, tmp))
                    ne_xc = math.ceil(maxl / 50)
                    ne_yc = math.ceil(len(tmp) / 50)
                    chunks = []
                    for i in range(ne_xc):
                        for j in range(ne_yc):
                            new_chunk = Chunk()
                            omap = []
                            tm = tmp[j*50 : j*50+50]
                            for k in range(50 - len(tm)):
                                tm.append([])
                            for k in tm:
                                t2 = list(k[i*50 : i*50+50])
                                for l in range(50 - len(t2)):
                                    t2.append(' ')
                                omap.append(list(t2))
                            new_chunk.map = omap
                            if j >= len(chunks):
                                chunks.append([new_chunk])
                            elif i >= len(chunks[j]):
                                chunks[j].append(new_chunk)
                            else:
                                chunks[j][i] = new_chunk

    screen.fill('white')
    chunk = font_f3.render("区块: X {} Y {}".format(chunk_x, chunk_y), True, (0, 0, 0))
    mouse = font_f3.render("鼠标: X {} Y {} (总 X {} Y {})".format(mouse_at[0], mouse_at[1], mouse_at[0]+(chunk_x*50), mouse_at[1]+(chunk_y*50)), True, (0, 0, 0))
    pygame.draw.line(screen, "gray", (0, 800), (800, 800))
    screen.blit(chunk, (10, 810))
    screen.blit(mouse, (10, 860))
    chunks[chunk_y][chunk_x].render(screen)
    for i, j in choosed:
        pygame.draw.rect(screen, 'red', pygame.Rect(i*16, j*16, 16, 2))
        pygame.draw.rect(screen, 'red', pygame.Rect(i*16, j*16, 2, 16))
        pygame.draw.rect(screen, 'red', pygame.Rect(i*16, j*16+14, 16, 2))
        pygame.draw.rect(screen, 'red', pygame.Rect(i*16+14, j*16, 2, 16))
    pygame.display.flip()